package com.bub.pay.framework.common.template;

import org.springframework.beans.BeanUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class EmailTemplate {

    private static final Map<String, EmailVo> templateMap = new HashMap<>();

    private static ExpressionParser parser = new SpelExpressionParser();

    public final static String TEMPLATE_OPEN = "1001";
    public final static String TEMPLATE_OPEN_MERCHANT = "1002";
    public final static String TEMPLATE_RESET_PASSWORD = "1003";
    public final static String TEMPLATE_RESET_PAY_PASS = "1004";
    public final static String TEMPLATE_RESET_KEY = "1005";
    private final static String TEMPLATE_RESET_PUBLIC_KEY = "1006";
    private final static String TEMPLATE_RESET_PRIVATE_KEY = "1007";
    private final static String TEMPLATE_RESET_SIGN_KEY = "1008";
    public final static String TEMPLATE_RESET_GOOGLE_SECRET = "1009";
    public final static String TEMPLATE_EMAIL_VERIFICATION_CODE = "1010";

    //币友总后台
    //新建商户
    public final static String TEMPLATE_ADMIN_NEW_BUILT_MERCHANT = "1011";


    //币友商户后台
    //新建商户员工
    public final static String TEMPLATE_NEW_BUILT_MERCHANT_EMPLOYEE = "1012";
    //重置密码
    public final static String TEMPLATE_RESET_MERCHANT_LOGIN_PASSWORD = "1013";
    //重置谷歌密钥
    public final static String TEMPLATE_RESET_MERCHANT_GOOGLE_SECRET = "1014";

    //总后台添加员工
    public final static String TEMPLATE_ADMIN_ADD_STAFF = "1015";

    // @formatter:off

    private final static String TITLE_OPEN = "【彩盟】开户成功";
    private final static String TITLE_OPEN_MERCHANT = "【彩盟】商户账户开户成功";
    private final static String TITLE_RESET_PASSWORD = "【彩盟】重置登陆密码";
    private final static String TITLE_RESET_PAY_PASS = "【彩盟】重置支付密码";
    private final static String TITLE_RESET_KEY = "【彩盟】重置{payTypeName}{restTitle}";
    private final static String TITLE_REST_PUBLIC_KEY = "【彩盟】重置{payTypeName}公钥";
    private final static String TITLE_REST_PRIVATE_KEY = "【彩盟】重置{payTypeName}私钥";
    private final static String TITLE_REST_SIGN_KEY = "【彩盟】重置{payTypeName}验签密钥";
    private final static String TITLE_RESET_GOOGLE_SECRET = "【彩盟】已重置谷歌验证码";
    private final static String TITLE_EMAIL_VERIFICATION_CODE = "【币友】{systemName}员工修改邮箱验证";

    //币友总后台
    private final static String TITLE_ADMIN_NEW_BUILT_MERCHANT = "【币友】总后台商户开户成功";

    //币友商户后台
    private final static String TITLE_NEW_BUILT_MERCHANT_EMPLOYEE = "【币友】商户平台员工开户成功";
    private final static String TITLE_MERCHANT_RESET_LOGIN_PASSWORD = "【币友】重置密码";
    private final static String TITLE_MERCHANT_RESET_GOOGLE_SECRET = "【币友】重置谷歌验证码";
    private final static String TITLE_ADMIN_ADD_STAFF = "【币友】总后台员工开户成功";


    //币友总后台
    //新建员工
    private final static String ADMIN_NEW_STAFF_CONTENT =
            "<p style=\"font-weight: bolder;font-size: 16px;\">您已经在币友总管理平台成功新建员工，首次登录请尽快更换密码；有权限问题或无法登录请联系管理员。\n" +
                    "\n</p>" +
                    "<p style=\"font-weight: bolder;font-size: 16px;\">账户名为：：<span style=\"font-size: 12px;font-weight: normal\">{username}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">初始登陆密码为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">谷歌验证码密钥： <span style=\"font-size: 12px;font-weight: normal\">{googleSecret}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">操作后台登录网址： http://console.bubchain.com</p><br></br><br></br><br></br>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">1.安装谷歌身份验证器，登录谷歌商店或App Store搜索 [iPhone设备Google Authenticator] 或 [Android设备 谷歌身份验证器]</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">2.下载并安装应用程序</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">3.添加您绑定的谷歌账户，然后用谷歌身份验证器App扫描二维码（QR CODE)</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">4.输入谷歌身份验证器产生的验证码</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">5.提交后将本账户绑定谷歌身份验证器整个流程完成</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">6.如需更改谷歌验证账户请联系客服人员</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">7.更多详情请查看Google官方指南</p>";
    //币友总后台
    //新建商户
    private final static String ADMIN_NEW_MERCHANT_CONTENT =
            "<p style=\"font-weight: bolder;font-size: 16px;\">您已经成功在币友平台创建商户账户，首次登录请尽快更换密码；有权限问题或无法登录请联系管理员。</p>" +
                    "<p style=\"font-weight: bolder;font-size: 16px;\">账户名为：：<span style=\"font-size: 12px;font-weight: normal\">{username}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">初始登陆密码为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">谷歌验证码密钥： <span style=\"font-size: 12px;font-weight: normal\">{googleSecret}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">操作后台登录网址： http://merchant.bubchain.com</p><br></br><br></br><br></br>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">1.安装谷歌身份验证器，登录谷歌商店或App Store搜索 [iPhone设备Google Authenticator] 或 [Android设备 谷歌身份验证器]</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">2.下载并安装应用程序</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">3.添加您绑定的谷歌账户，然后用谷歌身份验证器App扫描二维码（QR CODE)</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">4.输入谷歌身份验证器产生的验证码</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">5.提交后将本账户绑定谷歌身份验证器整个流程完成</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">6.如需更改谷歌验证账户请联系客服人员</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">7.更多详情请查看Google官方指南</p>";

    //币友商户后台
    //新建员工
    private final static String MERCHANT_NEW_EMPLOYEE_CONTENT =

            "<p style=\"font-weight: bolder;font-size: 16px;\">您已经成功在币友商户平台创建员工账户，首次登录请尽快更换密码；有权限问题或无法登录请联系管理员。</p>" +
                    "<p style=\"font-weight: bolder;font-size: 16px;\">账户名为：：<span style=\"font-size: 12px;font-weight: normal\">{username}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">初始登陆密码为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">谷歌验证码密钥： <span style=\"font-size: 12px;font-weight: normal\">{googleSecret}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">操作后台登录网址： http://merchant.bubchain.com</p><br></br><br></br><br></br>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">1.安装谷歌身份验证器，登录谷歌商店或App Store搜索 [iPhone设备Google Authenticator] 或 [Android设备 谷歌身份验证器]</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">2.下载并安装应用程序</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">3.添加您绑定的谷歌账户，然后用谷歌身份验证器App扫描二维码（QR CODE)</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">4.输入谷歌身份验证器产生的验证码</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">5.提交后将本账户绑定谷歌身份验证器整个流程完成</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">6.如需更改谷歌验证账户请联系客服人员</p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">7.更多详情请查看Google官方指南</p>";
    //重置登录
    public final static String MERCHANT_RESET_LOGIN_PASSWORD_CONTENT =
            "<p style=\"font-weight: bolder;font-size: 16px;\">【币友】您的平台账号：<span style=\"font-size: 12px;font-weight: normal\">{username}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">登录密码现已经重置为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">登录后请尽快更换登录密码，请妥善保存，不要向任何人透露。如果此操作非本人所为，请及时联系官方处理！</p>";

    //重置谷歌验证码
    public final static String MERCHANT_RESET_GOOGLE_SECRET_CONTENT =
            "<p style=\"font-weight: bolder;font-size: 16px;\">【币友】您的平台账号：<span style=\"font-size: 12px;font-weight: normal\">{username}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">谷歌验证码现已经重置为： <span style=\"font-size: 12px;font-weight: normal\">{googleSecret}</span></p>"
                    + "<p style=\"font-weight: bolder;font-size: 16px;\">如果此操作非本人所为，请及时联系官方处理！</p>";


    //
    private final static String CONTENT_OPEN = "<p style=\"font-weight: bolder;font-size: 16px;\">【彩盟】您已在平台成功开户，账户名为：<span style=\"font-size: 12px;font-weight: normal\">{userName}</span></p>"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">初始登陆密码为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">登录后请尽快更换登录密码，请妥善保存，不要向任何人透露。</p>";

    private final static String CONTENT_OPEN_MERCHANT = "<p style=\"font-weight: bolder;font-size: 16px;\">【彩盟】您已在平台成功开户，登录后请尽快更换密码。</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">账户名为：</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{userName}</span>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">初始登录密码为：</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{password}</span>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">操作后台登录网址：<span style=\"font-size: 12px;font-weight: normal\">https://sh.caimengpay.com</span></p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">对接密钥信息（此信息非常重要，请务必保管好，且不能泄漏）：</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">支付 MD5 key：</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{payMd5key}</span>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">支付的对接公钥（用于加密请求报文）</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{payPublicKey}</span>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">支付的对接私钥（用于解密回调报文）</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{payPrivateKey}</span>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">此信息非常重要，请妥善保存，不要向任何人透露。如需要重置，请联系客服。</p>";

    private final static String CONTENT_RESET_PASSWORD = "<p style=\"font-weight: bolder;font-size: 16px;\">【彩盟】您的平台账号：<span style=\"font-size: 12px;font-weight: normal\">{userName}</span></p>"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">登录密码现已经重置为： <span style=\"font-size: 12px;font-weight: normal\">{password}</span></p>"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">登录后请尽快更换登录密码，请妥善保存，不要向任何人透露。如果此操作非本人所为，请及时联系官方处理！</p>";

    private final static String CONTENT_RESET_PAY_PASS = "<p style=\"font-weight: bolder;font-size: 16px;\">【彩盟】您的平台账号：<span style=\"font-size: 12px;font-weight: normal\">{userName}</span></p>"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">支付密码已清空，登录后请重新设置。如果此操作非本人所为，请及时联系官方处理！</p>";

    private final static String CONTENT_RESET_KEY = "<p style=\"font-weight: bolder;font-size: 16px;\">【彩盟】您的平台账号：<span style=\"font-size: 12px;font-weight: normal\">$(#userName)</span></p>"
            + "$(#publicKey != null ? #template_" + TEMPLATE_RESET_PUBLIC_KEY + "_content : '')"
            + "$(#privateKey != null ? #template_" + TEMPLATE_RESET_PRIVATE_KEY + "_content : '')"
            + "$(#signKey != null ? #template_" + TEMPLATE_RESET_SIGN_KEY + "_content : '')"
            + "<p style=\"font-weight: bolder;font-size: 16px;\">此信息非常重要，请妥善保存，不要向任何人透露。如需要重置，请联系客服。</p>";

    private final static String CONTENT_REST_PUBLIC_KEY = "<p style=\"font-weight: bolder;font-size: 16px;\">已重置{payTypeName}公钥</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">{payTypeName}的对接公钥（用于加密请求报文）</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{publicKey}</span>";

    private final static String CONTENT_REST_PRIVATE_KEY = "<p style=\"font-weight: bolder;font-size: 16px;\">已重置{payTypeName}私钥</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">{payTypeName}的对接私钥（用于解密回调报文）</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{privateKey}</span>";

    private final static String CONTENT_REST_SIGN_KEY = "<p style=\"font-weight: bolder;font-size: 16px;\">已重置{payTypeName}验签密钥</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">{payTypeName}的验签密钥</p>" +
            "<span style=\"font-size: 12px;font-weight: normal\">{signKey}</span>";

    private final static String CONTENT_RESET_GOOGLE_SECRET = "<p style=\"font-weight: bolder;font-size: 16px;\">已重置谷歌验证码</p>" +
            "<p style=\"font-weight: bolder;font-size: 16px;\">请登陆后重新绑定谷歌验证码</p>";

    private final static String CONTENT_EMAIL_VERIFICATION_CODE = "<div id=\"u5310_text\" class=\"text \"><p style=\"font-size:13px;\">" +
            "<span>您正在币友{systemName}申请更换邮箱，请输入以下邮箱验证码完成操作，邮箱验证码将在</span><span style=\"color:#FF0000;\">30分钟</span><span>后失效；如果申请更换邮箱不是您本人操作请尽快修改密码或联系管理员处理，以防信息泄露。</span></p>" +
            "<p style=\"font-size:13px;\"><span><br></span></p><p style=\"font-size:13px;\"><span>员工ID： {userId}</span></p><p style=\"font-size:13px;\"><span>员工姓名： {userName}</span></p>" +
            "<p style=\"font-size:13px;\"><span>旧邮箱地址：{oldEmail}</span></p><p style=\"font-size:13px;\"><span>新邮箱地址：{newEmail}</span></p>" +
            "<p style=\"font-size:13px;\"><span><br></span></p><p style=\"font-size:18px;\"><span>本次邮箱验证码为：{verificationCode}</span></p></div>";

    // @formatter:on

    static {
        templateMap.put(TEMPLATE_OPEN, new EmailVo(TITLE_OPEN, CONTENT_OPEN));
        templateMap.put(TEMPLATE_OPEN_MERCHANT, new EmailVo(TITLE_OPEN_MERCHANT, CONTENT_OPEN_MERCHANT));
        templateMap.put(TEMPLATE_RESET_PASSWORD, new EmailVo(TITLE_RESET_PASSWORD, CONTENT_RESET_PASSWORD));
        templateMap.put(TEMPLATE_RESET_PAY_PASS, new EmailVo(TITLE_RESET_PAY_PASS, CONTENT_RESET_PAY_PASS));
        templateMap.put(TEMPLATE_RESET_KEY, new EmailVo(TITLE_RESET_KEY, CONTENT_RESET_KEY));
        templateMap.put(TEMPLATE_RESET_PUBLIC_KEY, new EmailVo(TITLE_REST_PUBLIC_KEY, CONTENT_REST_PUBLIC_KEY));
        templateMap.put(TEMPLATE_RESET_PRIVATE_KEY, new EmailVo(TITLE_REST_PRIVATE_KEY, CONTENT_REST_PRIVATE_KEY));
        templateMap.put(TEMPLATE_RESET_SIGN_KEY, new EmailVo(TITLE_REST_SIGN_KEY, CONTENT_REST_SIGN_KEY));
        templateMap.put(TEMPLATE_RESET_GOOGLE_SECRET, new EmailVo(TITLE_RESET_GOOGLE_SECRET, CONTENT_RESET_GOOGLE_SECRET));
        templateMap.put(TEMPLATE_EMAIL_VERIFICATION_CODE, new EmailVo(TITLE_EMAIL_VERIFICATION_CODE, CONTENT_EMAIL_VERIFICATION_CODE));
        templateMap.put(TEMPLATE_NEW_BUILT_MERCHANT_EMPLOYEE, new EmailVo(TITLE_NEW_BUILT_MERCHANT_EMPLOYEE, MERCHANT_NEW_EMPLOYEE_CONTENT));
        templateMap.put(TEMPLATE_RESET_MERCHANT_LOGIN_PASSWORD, new EmailVo(TITLE_MERCHANT_RESET_LOGIN_PASSWORD, MERCHANT_RESET_LOGIN_PASSWORD_CONTENT));
        templateMap.put(TEMPLATE_RESET_MERCHANT_GOOGLE_SECRET, new EmailVo(TITLE_MERCHANT_RESET_GOOGLE_SECRET, MERCHANT_RESET_GOOGLE_SECRET_CONTENT));
        templateMap.put(TEMPLATE_ADMIN_NEW_BUILT_MERCHANT, new EmailVo(TITLE_ADMIN_NEW_BUILT_MERCHANT, ADMIN_NEW_MERCHANT_CONTENT));
        templateMap.put(TEMPLATE_ADMIN_ADD_STAFF, new EmailVo(TITLE_ADMIN_ADD_STAFF, ADMIN_NEW_STAFF_CONTENT));

    }

    public static EmailVo getContent(String templateId, Map<String, String> data) {
        EmailVo sourceModel = templateMap.get(templateId);
        if (sourceModel == null) {
            return null;
        }

        handlerTemplateDataVariable(data);

        String title = sourceModel.getTitle();
        String content = sourceModel.getContent();

        EmailVo destinationModel = new EmailVo();
        BeanUtils.copyProperties(sourceModel, destinationModel);

        destinationModel.setTitle(processTemplate(title, data));
        destinationModel.setContent(processTemplate(content, data));
        return destinationModel;
    }

    /**
     * 处理模板
     *
     * @param template     模板
     * @param dataVariable 数据变量
     * @return 处理完毕后的模板
     */
    private synchronized static String processTemplate(String template, Map<String, String> dataVariable) {
        // 以模板方式解析
        EvaluationContext context = new StandardEvaluationContext();
        for (String key : dataVariable.keySet()) {
            String value = dataVariable.get(key);
            context.setVariable(key, value);
        }
        Expression expression = parser.parseExpression(template, TEMPLATE_EXPRESSION);
        template = expression.getValue(context, String.class);
        if (template == null) {
            template = "";
        }
        // 转换{}变量
        for (String key : dataVariable.keySet()) {
            String value = dataVariable.get(key);
            if (template.contains(key)) {
                template = template.replaceAll("\\{" + key + "\\}", value);
            }
        }
        return template;
    }

    /**
     * 处理模板数据
     *
     * @param dataVariable 数据变量
     */
    private static void handlerTemplateDataVariable(Map<String, String> dataVariable) {
        Set<Map.Entry<String, EmailVo>> entrySet = templateMap.entrySet();
        for (Map.Entry<String, EmailVo> entry : entrySet) {
            String templateId = entry.getKey();
            EmailVo emailVo = entry.getValue();
            dataVariable.put(String.format("template_%s_title", templateId), emailVo.getTitle());
            dataVariable.put(String.format("template_%s_content", templateId), emailVo.getContent());
        }
    }


    /**
     * 表达式模板解析器
     * 当使用此解析器时
     * 只有$()内的内容才会被识别为表达式进行解析
     */
    private static final ParserContext TEMPLATE_EXPRESSION = new ParserContext() {

        @Override
        public boolean isTemplate() {
            return true;
        }

        @Override
        public String getExpressionPrefix() {
            return "$(";
        }

        @Override
        public String getExpressionSuffix() {
            return ")";
        }
    };

}
